package com.wan37.gate.handler;

import com.google.protobuf.Message;
import com.wan37.gate.domain.ClientConnection;
import com.wan37.gate.global.maps.ClientConnectionMap;
import com.wan37.protobuf.analysis.ParseMap;
import com.wan37.protobuf.constant.PtoNum;
import com.wan37.protobuf.message.client2server.game.*;
import com.wan37.protobuf.message.internal.Internal;
import com.wan37.protobuf.util.ServerProtoUtils;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;

/**
 * @author : luoyong
 * @date : 2020-05-27 11:31
 **/
public class GateToLogicConnectionHandler extends SimpleChannelInboundHandler<Message> {

    private static final Logger logger = LoggerFactory.getLogger(GateToLogicConnectionHandler.class);

    private static ChannelHandlerContext gateToLogicConnectionContext;

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        gateToLogicConnectionContext = ctx;
        logger.info("[GateServer to LogicServer] 连接已经建立成功");

        //向LogicServer发送Greet协议消息
        sendGreetToLogicServer();
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {

        gateToLogicConnectionContext = null;
        logger.info("[GateServer to LogicServer] 连接已经断开.");
    }

    /**
     * 向LogicServer发送Greet协议消息。
     */
    private void sendGreetToLogicServer() {

        Internal.Greet.Builder greet = Internal.Greet.newBuilder();
        greet.setFrom(Internal.Greet.From.Gate);

        ByteBuf buf = ServerProtoUtils.pack2Server(Internal.DestType.Logic, -1, "admin", PtoNum.GREET, greet.build());

        ChannelFuture future = gateToLogicConnectionContext.writeAndFlush(buf);
        future.addListener(new ChannelFutureListener() {
            @Override
            public void operationComplete(ChannelFuture channelFuture) throws Exception {
                logger.info("GateServer 向 LogicServer 发送了 Greet 消息.");
            }
        });

    }

    public static ChannelHandlerContext getGateToLogicConnectionContext() {
        return gateToLogicConnectionContext;
    }

    @Override
    protected void channelRead0(ChannelHandlerContext channelHandlerContext, Message message) throws Exception {
        //收到LogicServer处理之后的消息
        logger.info("[GateServer] 收到经过[LogicServer]处理之后的消息[{}].", message.getClass().getSimpleName());
        //解析消息
        Internal.GTransfer gTransfer = (Internal.GTransfer) message;
        Internal.DestType destType = gTransfer.getDest();
        gTransfer.getMsg();
        if (destType == Internal.DestType.Client) {
            //如果目的地: 客户端
            //获得message
            Message message1 = ParseMap.getMessage(gTransfer.getPtoNum(), gTransfer.getMsg().toByteArray());
            ByteBuf buf = ServerProtoUtils.pack2Client(message1);
            if (message1 instanceof Game.SGameAttackBroadcast) {
                List<GameEntity.stringMsg> userIds = ((Game.SGameAttackBroadcast) message1).getUserIdList();
                broadCastMessageHandler(userIds, buf);
            } else if (message1 instanceof GameServerResponse.AoiBroadcastResponse) {
                List<GameEntity.stringMsg> userIds = ((GameServerResponse.AoiBroadcastResponse) message1).getReceiverIdList();
                broadCastMessageHandler(userIds, buf);
            } else if (message1 instanceof GameServerResponse.AoiRoleBroadcastResponse) {
                List<GameEntity.stringMsg> userIds = ((GameServerResponse.AoiRoleBroadcastResponse) message1).getReceiverIdList();
                broadCastMessageHandler(userIds, buf);

            } else if (message1 instanceof GameFighting.AttackBroadcastResponse) {
                List<GameEntity.stringMsg> userIds = ((GameFighting.AttackBroadcastResponse) message1).getReceiverIdList();
                broadCastMessageHandler(userIds, buf);
            } else {
                long netId = ClientConnectionMap.userIdNetIdMap.get(gTransfer.getUserId());
                ClientConnectionMap.getClientConnection(netId).getCtx().writeAndFlush(buf);
            }
        } else if (destType == Internal.DestType.Gate) {
            Message message1 = ParseMap.getMessage(gTransfer.getPtoNum(), gTransfer.getMsg().toByteArray());
            if (message1 instanceof Game.GGameUserLogoutMsg) {
                ClientConnection clientConnection = ClientConnectionMap.getClientConnection(((Internal.GTransfer) message).getNetId());
                //从clientConnectionMap中移除对应的clientConnection
                ClientConnectionMap.removeClientConnection(clientConnection);
            } else if (message1 instanceof GameChat.WorldPlayerChatBroadcast) {
                GameChat.WorldPlayerChatBroadcast worldPlayerChatBroadcast = (GameChat.WorldPlayerChatBroadcast) message1;
                ByteBuf byteBuf = ServerProtoUtils.pack2Client(worldPlayerChatBroadcast.getChatResponse());
                broadCastMessageHandler(worldPlayerChatBroadcast.getReceiverIdList(), byteBuf);
            } else if (message1 instanceof GameBackpack.SWeaponryBroadcastResponse) {
                GameBackpack.SWeaponryBroadcastResponse weaponryBroadcastResponse = (GameBackpack.SWeaponryBroadcastResponse) message1;
                for (GameBackpack.UserIdToWeaponry userIdToWeaponry : weaponryBroadcastResponse.getUserIdToWeaponryList()) {
                    ByteBuf byteBuf = ServerProtoUtils.pack2Client(userIdToWeaponry);
                    broadCastMessageHandler(weaponryBroadcastResponse.getReceiverIdList(), byteBuf);
                }
            } else if (message1 instanceof GameBackpack.UseItemBroadcastResponse) {
                GameBackpack.UseItemBroadcastResponse useItemBroadcastResponse = (GameBackpack.UseItemBroadcastResponse) message1;
                for (GameBackpack.UserIdToItem userIdToItem : useItemBroadcastResponse.getUserIdToItemList()) {
                    ByteBuf byteBuf = ServerProtoUtils.pack2Client(userIdToItem);
                    broadCastMessageHandler(useItemBroadcastResponse.getReceiverIdList(), byteBuf);
                }
            } else if (message1 instanceof Game.SkillResponseBroadcast) {
                Game.SkillResponseBroadcast skillResponseBroadcast = (Game.SkillResponseBroadcast) message1;
                for (Game.SGameSkillResponse sGameSkillResponse : skillResponseBroadcast.getSGameSkillResponseList()) {
                    ByteBuf byteBuf = ServerProtoUtils.pack2Client(sGameSkillResponse);
                    broadCastMessageHandler(skillResponseBroadcast.getReceiverIdList(), byteBuf);
                }
            }else if (message1 instanceof GameEmail.EmailBroadcast){
                GameEmail.EmailBroadcast emailBroadcast = (GameEmail.EmailBroadcast) message1;
                ByteBuf byteBuf = ServerProtoUtils.pack2Client(emailBroadcast.getEmailResponse());
                broadCastMessageHandler2(emailBroadcast.getReceiverIdList(), byteBuf);
            }
        }
    }

    /**
     * 处理发送给逻辑服务器的移动消息
     *
     * @param userIds
     */
    private void broadCastMessageHandler(List<GameEntity.stringMsg> userIds, ByteBuf buf) {
        for (GameEntity.stringMsg stringMsg : userIds) {
            if (ClientConnectionMap.userIdNetIdMap.containsKey(stringMsg.getStringId())) {
                long netId1 = ClientConnectionMap.userIdNetIdMap.get(stringMsg.getStringId());
                if (ClientConnectionMap.getClientConnection(netId1).getCtx() != null) {
                    ClientConnectionMap.getClientConnection(netId1).getCtx().writeAndFlush(buf.retain());
                }
            }
        }
    }

    /**
     * Email使用了自己类中定义的StringMsg导致来源和上面不一样
     * @param userIds
     * @param buf
     */
    private void broadCastMessageHandler2(List<GameEmail.StringMsg> userIds, ByteBuf buf) {
        for (GameEmail.StringMsg stringMsg : userIds) {
            if (ClientConnectionMap.userIdNetIdMap.containsKey(stringMsg.getStringId())) {
                long netId1 = ClientConnectionMap.userIdNetIdMap.get(stringMsg.getStringId());
                if (ClientConnectionMap.getClientConnection(netId1).getCtx() != null) {
                    ClientConnectionMap.getClientConnection(netId1).getCtx().writeAndFlush(buf.retain());
                }
            }
        }
    }


}
